/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sirtet.tetris;

import java.util.LinkedList;
import sirtet.GameAction;
import sirtet.GameBoard;
import sirtet.Piece;
import sirtet.PieceProvider;
import sirtet.netplay.ClientResponse;
import sirtet.netplay.NetworkPlayer;
import sirtet.netplay.event.CommunicationDataEvent;
import sirtet.netplay.event.CommunicationEvent;
import sirtet.netplay.event.CommunicationListener;

/**
 * Buffer next pieces sent from the server and provide them to the GameBoard.
 * @author guangwei.zhu
 */
public class RemotePieceProvider extends PieceProvider {

    private NetworkPlayer player;
    private LinkedList<TetrisPiece> pieces = new LinkedList<TetrisPiece>();
    private CommunicationListener listener = new CommunicationListener() {

        public void communicationDisconnected(CommunicationEvent evt) {
            dispose();
        }

        public void communicationDataReceived(CommunicationDataEvent evt) {
            GameAction action = GameAction.fromString(evt.data);
            if (action == null || !action.actor.equals(player.id())) {
                return;     // Nothing to do
            }
            String strPiece = ClientResponse.parse(GameBoard.MSG_PIECE, action.command);
            if (strPiece != null) {
                addPiece(new TetrisPieceFactory().fromString(strPiece));
            }
        }
    };

    private synchronized void addPiece(TetrisPiece piece) {
        pieces.addLast(piece);
        notifyAll();
    }

    @Override
    public synchronized Piece requestPiece() {
        try {
            while (pieces.size() == 0) {
                wait();
            }
            return pieces.pollFirst();
        } catch (Exception ex) {
            return null;
        }
    }

    /**
     * Construct an instance who is related to a NetworkPlayer.  Only pieces sent
     * from the server side and specifically to the related player will be buffered
     * and provided through this instance.
     * @param player the related NetworkPlayer
     */
    public RemotePieceProvider(NetworkPlayer player) {
        this.player = player;
        player.getCommunicator().addCommunicationListener(listener);
    }

    public void dispose() {
        player.getCommunicator().removeCommunicationListener(listener);
        player = null;
    }

    @Override
    public int remaining() {
        return Math.min(1, pieces.size());
    }
}
